package com.yonyou.cyxdms.sysAuth.service.config;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author lijun
 * @version V1.0
 * @Title: Redis
 * @Descripttion: redis对template封装
 */
@Component
public class Redis extends StringRedisTemplate {
    public static final String SPLIT_KEY = "#";
    private final Logger logger = LoggerFactory.getLogger(Redis.class);

    public Redis(RedisConnectionFactory connectionFactory) {
        super(connectionFactory);
    }

    //Key（键），redis的key操作

    /**
     * 拼接多个key
     *
     * @param keys
     */
    public static String mergeKey(String... keys) {
        StringBuilder result = new StringBuilder();
        for (String key : keys) {
            result.append(key).append(SPLIT_KEY);
        }
        result.deleteCharAt(result.length() - 1);

        return result.toString();
    }

    /**
     * 分隔key
     *
     * @param key
     * @return
     */
    public static String[] splitKey(String key) {
        return key.split(SPLIT_KEY);
    }

    /**
     * 删除key
     *
     * @param key
     */
    public void DEL(String key) {
        try {
            super.delete(key);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 实现命令：EXISTS key，判断KEY是否存在。
     *
     * @param key
     * @return value
     */
    public Boolean EXISTS(String key) {
        return super.hasKey(key);
    }

    /**
     * 实现命令：EXPIRE key，设置过期时间
     *
     * @param key
     * @return value
     */
    public Boolean EXPIRE(String key, int expire, TimeUnit timeUnit) {
        return super.expire(key, expire, timeUnit);
    }

    /**
     * 实现命令：EXPIREAT key，设置过期日期。
     *
     * @param key
     * @param datetime
     * @return value
     */
    public Boolean EXPIREAT(String key, Date datetime) {
        return super.expireAt(key, datetime);
    }

    /**
     * 实现命令：KEYS pattern ，模糊查询key的值。
     *
     * @param pattern
     * @return value
     */
    public Set<String> KEYS(String pattern) {
        return super.keys(pattern);
    }

    /**
     * 实现命令：MOVE key db
     *
     * @param key
     * @param dbindex
     * @return value
     */
    public Boolean MOVE(String key, int dbindex) {
        return super.move(key, dbindex);
    }

    /**
     * 实现命令：PERSIST key ，移除过期时间
     *
     * @param key
     * @return value
     */
    public Boolean PERSIST(String key) {
        return super.persist(key);
    }

    /**
     * 实现命令：GET key，返回 key所关联的字符串值。
     *
     * @param key
     * @return value
     */
    public <T> T GET(String key, Class<T> tClass) {
        try {
            String str = opsForValue().get(key);
            //判断返回是否为空
            if (str != null) {
                return JSON.parseObject(str, tClass);
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }

    /**
     * 设置k-v
     * 自定义过期时间,自定义时间单位
     *
     * @param key
     * @param value
     * @param expire
     * @param timeUnit
     */
    public void SETEX(String key, Object value, int expire, TimeUnit timeUnit) {
        try {
            opsForValue().set(key, JSON.toJSONString(value), expire, timeUnit);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 在hash表增加记录
     *
     * @param key   表名
     * @param field 行记录名
     * @param value 值
     */
    public void HSET(String key, String field, Object value) {
        try {
            super.opsForHash().put(key, field, JSON.toJSONString(value));
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 在批量设置hash表增加记录
     *
     * @param key    表名
     * @param fields 行记录名
     */
    public void HMSET(String key, Map<String, Object> fields) {
        try {
            Map<String, String> m = new HashMap<>();

            fields.forEach((k, v) -> m.put(k, JSON.toJSONString(v)));

            super.opsForHash().putAll(key, m);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 在批量获取hash表增加记录
     *
     * @param key    表名
     * @param fields 行记录名
     */
    public <T> List<T> HMGET(String key, Set<String> fields, Class<T> tClass) {
        try {
            List<T> result = new ArrayList<>();

            List obj = super.opsForHash().multiGet(key, (Collection) fields);
            if (obj == null || obj.size() == 0) {
                return null;
            } else {
                for (Object o : obj) {
                    result.add(o == null ? null : JSON.parseObject(o.toString(), tClass));
                }
            }

            return result;
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }

    /**
     * 获取hash表数据
     *
     * @param key
     * @param field
     * @return
     */
    public <T> T HGET(String key, String field, Class<T> tClass) {
        try {
            Object obj = super.opsForHash().get(key, field);
            if (obj == null) {
                return null;
            }
            return JSON.parseObject(obj.toString(), tClass);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }

    public String HGETArry(String key, String field) {
        try {
            Object obj = super.opsForHash().get(key, field);
            if (null == obj) {
                return null;
            }
            return obj.toString();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }

    /**
     * 获取hash表全部数据
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> HGETALL(String key, Class<T> tClass) {
        try {
            HashMap<String, T> result = new HashMap<>();

            Map<Object, Object> obj = opsForHash().entries(key);
            if (obj == null || obj.size() == 0) {
                return null;
            } else {
                obj.forEach((k, v) -> result.put(k.toString(), JSON.parseObject(v.toString(), tClass)));
            }

            return result;
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }

    /**
     * 删除一个或多个HASH FIELD
     *
     * @param key
     * @param fields
     */
    public Long HDEL(String key, Object... fields) {
        try {
            return opsForHash().delete(key, fields);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return 0L;
        }
    }

    /**
     * 获取多个key的value
     *
     * @param keys key列表
     */
    public <T> Map<String, T> MGET(List<String> keys, Class<T> tClass) {
        try {
            Map<String, T> result = new HashMap<>();

            List<String> obj = opsForValue().multiGet((Collection) keys);

            if (obj == null || obj.size() == 0) {
                return null;
            } else {
                for (String key : keys) {
                    result.put(key, key == null ? null : JSON.parseObject(key, tClass));
                }
            }

            return result;
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        return null;
    }

    /**
     * 设置多个key的value
     *
     * @param keys key-value列表
     */
    public void MSET(Map<String, Object> keys) {
        try {
            Map<String, String> m = new HashMap<>();

            keys.forEach((k, v) -> m.put(k, JSON.toJSONString(v)));

            super.opsForValue().multiSet(m);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * key不存在则设置value
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean setIfAbsent(String key, Object value) {
        return super.opsForValue().setIfAbsent(key, JSON.toJSONString(value));
    }

    /**
     * 获取旧值设置新值
     *
     * @param key
     * @param value
     * @return
     */
    public String getAndSet(String key, Object value) {
        return super.opsForValue().getAndSet(key, JSON.toJSONString(value));
    }

    /**
     * 消息发送
     *
     * @param channel
     * @param message
     */
    @Override
    public void convertAndSend(String channel, Object message) {
        super.opsForList().leftPush(channel, JSON.toJSONString(message));
    }
}
